package com.basic.common;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.log4j.Logger;

/**
 * 该类需要在WINDOWS系统下，安装WINRAR才能执行
 * @author lh
 *
 */
public class RarTool {
	private static Logger logger = Logger.getLogger ( RarTool.class.getName () );
	private String path = "C:\\Program Files\\WinRAR\\Rar.exe";

	/**
	 * 设置winrar安装路径
	 * 
	 * @param path
	 */
	public void setProgramPath(String path) {
		path=path+"\\Rar.exe";
		this.path = path;
		
	}

	/**
	 * 压缩文件
	 * 
	 * @param filePath
	 *            要压缩文件的路径
	 * @param rarFileName
	 *            压缩文件的文件名(包含路径和文件名)
	 * @param type
	 *            : 压缩类型(rar,zip)
	 * @return
	 */
	public boolean packageFile(String filePath, String rarFileName, String type) {
		if (type.equals("rar")) {
			rar(filePath, rarFileName);
		} else if (type.equals("zip")) {
			zip(filePath, rarFileName);
		}
		return true;
	}

	public static void main(String[] args) {
		RarTool tool = new RarTool();
		// tool.zip("d:/temp", "d:/test.zip");
		// tool.rar("d:/temp", "d:/test.rar");
		tool.unPackageFile("E:/rartest/rartest.rar", "E:/rartest/temp");
	}

	/**
	 * 将1个文件压缩成RAR格式 rarName 压缩后的压缩文件名(不包含后缀) fileName 需要压缩的文件名(必须包含路径) destDir
	 * 压缩后的压缩文件存放路径
	 * 
	 */
	private String rarCmd = " a ";

	private synchronized void rar(String destDir, String rarName) {
		rarCmd = path + rarCmd + rarName + " " + destDir;
		Runtime rt = null;
		Process p = null;
		try {
			rt = Runtime.getRuntime();
			p = rt.exec(rarCmd);
			InputStreamReader isr = new InputStreamReader(p.getInputStream());
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null) { 
			}
			isr.close();
			br.close();
			p.destroy();
		} catch (Exception e) {
			logger.error(FuncStatic.errorTrace(e));
		}
		finally{
			try { 
				p.destroy();
				rt.freeMemory();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private final int BUFFEREDSIZE = 1024;

	private synchronized void zip(String inputFilename, String zipFilename) {
		try {
			zip(new File(inputFilename), zipFilename);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private synchronized void zip(File inputFile, String zipFilename)
			throws IOException {
		ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
				zipFilename));
		try {
			zip(inputFile, out, inputFile.getName());
		} catch (IOException e) {
			throw e;
		} finally {
			out.close();
		}
	}

	private synchronized void zip(File inputFile, ZipOutputStream out,
			String base) throws IOException {
		if (inputFile.isDirectory()) {
			File[] inputFiles = inputFile.listFiles();
			out.putNextEntry(new ZipEntry(base + "/"));
			base = base.length() == 0 ? "" : base + "/";
			for (int i = 0; i < inputFiles.length; i++) {
				zip(inputFiles[i], out, base + inputFiles[i].getName());
			}

		} else {
			if (base.length() > 0) {
				out.putNextEntry(new ZipEntry(base));
			} else {
				out.putNextEntry(new ZipEntry(inputFile.getName()));
			}

			FileInputStream in = new FileInputStream(inputFile);
			try {
				int c;
				byte[] by = new byte[BUFFEREDSIZE];
				while ((c = in.read(by)) != -1) {
					out.write(by, 0, c);
				}
			} catch (IOException e) {
				throw e;
			} finally {
				in.close();
			}
		}
	}

	private String unrarCmd = " x ";

	/**
	 * 解压文件
	 * 
	 * @param fileName压缩文件的文件名
	 * @param toFilePath
	 *            解压路径
	 * @return
	 */
	public boolean unPackageFile(String fileName, String toFilePath) {
		fileName="\""+fileName+"\"";
		toFilePath="\""+toFilePath+"\"";
		unrarCmd = path + unrarCmd + fileName + " " + toFilePath;
		Runtime rt =  null;
		Process p = null;
		InputStreamReader isr = null;
		OutputStreamWriter osw = null;
		try {
			rt = Runtime.getRuntime();
			p = rt.exec(unrarCmd);
			isr = new InputStreamReader(p.getInputStream());
			osw = new OutputStreamWriter(p.getOutputStream());
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			while ((line = br.readLine()) != null) {
			}
			br.close();
			
		} catch (Exception e) {
			logger.error(FuncStatic.errorTrace(e));
			return false;
		}
		finally{
			try {
				isr.close();
				osw.close(); 
				p.destroy();
				rt.freeMemory();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		return true;
	}

}
